﻿/*
* Decorator is adding interception methods to the instance,
* i.e if you have class A with method m1, and decorator D with method m1
* then after attaching decorator, calling m1 on A first will call m1 on D
*/

var Decorator = (function () {
    return {
        attach: function (/*Target element*/target, /*Decorator element*/decorator) {
            for (var prop in decorator) {
                if (typeof target[prop] !== undefined) {
                    var originalMethod = target[prop];
                    var method = target[prop] = function () {
                        decorator.context = { stopPropagation: false, target: target, originalMethod: originalMethod };
                        decorator[prop].apply(decorator, arguments);
                        if (!decorator.context.stopPropagation) {
                            originalMethod.apply(target, arguments);
                        }
                        delete decorator.context;
                    }

                    method.__decorator = decorator;
                    method.__originalMethod = originalMethod;
                }
            }
        },
        detach: function (/*Target element*/target, /*Decorator element*/decorator) {
            for (var prop in target) {
                if (target.hasOwnProperty(prop)) {
                    var method = target[prop];
                    if (method.__decorator === decorator) {
                        target[prop] = method.__originalMethod;
                    }
                }
            }
        }
    };
})();